package com.liting.uitest.imgutils;

import com.liting.uitest.model.*;
import com.liting.uitest.service.impl.ImageCacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;

@Service
@Slf4j
public class VisionIntensionService {
    @Autowired
    private ImageCacheService cacheService;
    @Autowired
    private VisionExecutor visionExecutor;

    public BigDecimal visionIntentCalc(Long fileId, double length, List<Rectangle> rectList, List<Circle> cirList, List<ModuleImport> moduleImportList) throws Exception {
        ImageInfo imageInfo = cacheService.getImage(fileId);
        if (imageInfo == null) {
            throw new Exception("文件不存在");
        }
        //5个半径长
        BigDecimal[] rList = VisionIntensionUtils.getRlist(length);
        //正方形边长
        BigDecimal sideLength = VisionIntensionUtils.getSideLenth(rList[0]);
        //将图像分为小正方形，确定每个正方形的等级
        VisionIntentSquareAggreGation squareAggreGation = createSquare(imageInfo, sideLength, rList);

        //获取每个模块的重要度
        Map<String, Double> moduleImport = VisionIntensionUtils.getImportInfo(moduleImportList, rectList, cirList);


        Map<String, Map<Integer, Integer>> moduleSquareMap = new HashMap<>();
        CompletableFuture<Map<String, Map<Integer, Integer>>>[] resultArray = new CompletableFuture[rectList.size() + cirList.size()];
        int temp = 0;

        //每个模块包括的正方形信息
        for (Rectangle rectangle : rectList) {
            resultArray[temp++] = visionExecutor.createRectGradeSquareMap(rectangle, squareAggreGation);
            //Map<Integer,Integer> gradeSquareMap=VisionIntensionUtils.createRectGradeSquareMap(rectangle,squareAggreGation);

        }

        for (Circle circle : cirList) {
            resultArray[temp++] = visionExecutor.createCircleradeSquareMap(circle, squareAggreGation);
            //moduleSquareMap.put(circle.getName(),cirGradeSquareMap);
        }
        CompletableFuture.allOf(resultArray).join();

        try {
            for (int j = 0; j < resultArray.length; j++) {
                moduleSquareMap.putAll(resultArray[j].get());
            }
        } catch (Exception ex) {
            log.error("异步处理失败", ex);
            throw new Exception("计算失败");
        }


        //根据模块的重要度和正方形信息计算视觉强度
        BigDecimal result = VisionIntensionUtils.calcVisionIntent(moduleImport, moduleSquareMap);

        return result;
    }


    /**
     * 将图像分为小正方形，确定每个正方形的等级
     *
     * @param imageInfo
     * @param sideLength
     * @param rList
     * @return
     */
    public VisionIntentSquareAggreGation createSquare(ImageInfo imageInfo, BigDecimal sideLength, BigDecimal[] rList) throws Exception {
        VisionIntentSquareAggreGation squareAggreGation = new VisionIntentSquareAggreGation();

        int width = imageInfo.getWidth();
        int height = imageInfo.getHeight();

        double imgCenterX = width / 2;
        double imgCenterY = height / 2;

        int yCount = new BigDecimal(imgCenterY).divide(sideLength, BigDecimal.ROUND_DOWN).intValue();
        int xCount = new BigDecimal(imgCenterX).divide(sideLength, BigDecimal.ROUND_DOWN).intValue();

        double minX = imgCenterX - xCount * (sideLength.doubleValue());
        double minY = imgCenterY - yCount * (sideLength.doubleValue());
        double maxX = imgCenterX + xCount * (sideLength.doubleValue());
        double maxY = imgCenterY + xCount * (sideLength.doubleValue());

        squareAggreGation.setSquareSide(sideLength.doubleValue());
        squareAggreGation.setMaxY(maxY);
        squareAggreGation.setMaxX(maxX);
        squareAggreGation.setMinX(minX);
        squareAggreGation.setMinY(minY);

        List<CompletableFuture<VisionIntentSquareAggreGation>> futureList = new ArrayList<>();


        int temp = 200;

        for (int i = 0; i <= xCount * 2; i = i + temp) {
            for (int j = 0; j <= yCount * 2; j = j + temp) {
                if (i + temp < xCount * 2) {
                    if (j + temp < yCount * 2) {
                        futureList.add(visionExecutor.createSquareInner(minX, minY, i, i + temp, j, j + temp,
                                imgCenterX, imgCenterY, rList,
                                sideLength));
                    } else {
                        futureList.add(visionExecutor.createSquareInner(minX, minY, i, i + temp, j, yCount * 2 + 1,
                                imgCenterX, imgCenterY, rList,
                                sideLength));
                    }
                } else {
                    if (j + temp < yCount * 2) {
                        futureList.add(visionExecutor.createSquareInner(minX, minY, i, xCount * 2 + 1, j, j + temp,
                                imgCenterX, imgCenterY, rList,
                                sideLength));
                    } else {
                        futureList.add(visionExecutor.createSquareInner(minX, minY, i, xCount * 2 + 1, j, yCount * 2 + 1,
                                imgCenterX, imgCenterY, rList,
                                sideLength));
                    }
                }

            }
        }


        // 手动阻塞主线程,直至业务线程完成返回
        CompletableFuture<VisionIntentSquareAggreGation>[] resultArray = new CompletableFuture[futureList.size()];
        int i = 0;
        for (CompletableFuture<VisionIntentSquareAggreGation> future : futureList) {
            resultArray[i++] = future;
        }
        CompletableFuture.allOf(resultArray).join();

        Map<VisionIntentSquare, Integer> squreGradeMap = new HashMap<>();

        HashSet<BigDecimal> centerXSet = new HashSet<>();
        HashSet<BigDecimal> centerYSet = new HashSet<>();

        try {
            for (int j = 0; j < resultArray.length; j++) {
                squreGradeMap.putAll(resultArray[j].get().getSqureGradeMap());
                centerXSet.addAll(resultArray[j].get().getCenterXSet());
                centerYSet.addAll(resultArray[j].get().getCenterYSet());
            }
        } catch (Exception ex) {
            log.error("异步处理失败", ex);
            throw new Exception("计算失败");
        }

        List<BigDecimal> centerXList = new ArrayList<>(centerXSet);
        Collections.sort(centerXList);
        squareAggreGation.setCenterXList(centerXList);

        List<BigDecimal> centerYList = new ArrayList<>(centerYSet);
        Collections.sort(centerYList);
        squareAggreGation.setCenterYList(centerYList);


        squareAggreGation.setSqureGradeMap(squreGradeMap);

        return squareAggreGation;
    }


}
